package com.corx.network.mysqlstorage.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.corx.network.config.properties.MqttConfig;
import com.corx.network.config.properties.NetworkConfig;
import com.corx.network.core.exception.NetworkException;
import com.corx.network.core.type.NetworkTypeEnum;
import com.corx.network.mysqlstorage.model.DevicePointParam;
import com.corx.network.mysqlstorage.model.MqttDevicePointParam;
import com.corx.network.mysqlstorage.model.Network;
import lombok.extern.slf4j.Slf4j;


/**
 * @author gx
 * @version 1.0.0
 */
@Slf4j
public class ConfigUtil {

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();


    public static NetworkConfig parseConfigJson(Network network) throws NetworkException {

        try {
            if (NetworkTypeEnum.MQTT_CLIENT == NetworkTypeEnum.getByType(network.getType())) {
                MqttConfig mqttConfig = OBJECT_MAPPER.readValue(network.getConfig(), MqttConfig.class);
                mqttConfig.setKey(network.getId().toString());
                mqttConfig.setType(NetworkTypeEnum.getByType(network.getType()));
                if (mqttConfig.getKey() == null || mqttConfig.getKey().isEmpty()) {
                    throw new NetworkException(String.format("网络组件配置参数[key]是空的，NetworkType = %s, Network = %s", network.getType(), network));
                }
                if (mqttConfig.getUrl() == null || mqttConfig.getUrl().isEmpty()) {
                    throw new NetworkException(String.format("网络组件配置参数[url]是空的，NetworkType = %s, Network = %s", network.getType(), network));
                }
                if (mqttConfig.getUsername() == null || mqttConfig.getUsername().isEmpty()) {
                    throw new NetworkException(String.format("网络组件配置参数[username]是空的，NetworkType = %s, Network = %s", network.getType(), network));
                }
                if (mqttConfig.getPassword() == null || mqttConfig.getPassword().isEmpty()) {
                    throw new NetworkException(String.format("网络组件配置参数[password]是空的，NetworkType = %s, Network = %s", network.getType(), network));
                }
                return mqttConfig;
            }
        } catch (Exception e) {
            throw new NetworkException(String.format("读取网络组件配置信息异常，NetworkType = %s, Network = %s ", network.getType(), network), e);
        }
        throw new NetworkException(String.format("读取网络组件配置信息无法识别的的网络类型 ，NetworkType = %s ， Network = %s", network.getId(), network));

    }

    public static DevicePointParam parseParam(NetworkTypeEnum typeEnum, String paramsJson) throws NetworkException {

        try {
            if (NetworkTypeEnum.MQTT_CLIENT == typeEnum) {
                MqttDevicePointParam mqttDevicePointParam = OBJECT_MAPPER.readValue(paramsJson, MqttDevicePointParam.class);
                validateMqttTopic(mqttDevicePointParam.getTopic());
                return mqttDevicePointParam;
            }
        } catch (JsonProcessingException e) {
            throw new NetworkException(String.format("读取设备端点配置转换为DevicePointParam.class发生了异常， type = %s ，paramsJson = %s", typeEnum, paramsJson), e);
        }

        throw new NetworkException(String.format("读取设备端点配置无法识别的的网络类型 ，type = %s ， paramsJson = %s", typeEnum.getType(), paramsJson));
    }

    private static void validateMqttTopic(String topic) throws NetworkException {
        if (topic == null || topic.isEmpty()) {
            throw new NetworkException(String.format("Topic为空 ，topic = %s", topic));
        }
        if (topic.length() > 65535) {
            throw new NetworkException(String.format("Topic长度超出限制 ，topic = %s", topic));
        }
        if (topic.contains(" ")) {
            throw new NetworkException(String.format("Topic不能包含空格，topic = %s", topic));
        }
        if (topic.contains("#")) {
            // '#'只能出现在最后，并且要么是单独一个 #，要么前面是'/'
            if (!topic.equals("#") && !topic.endsWith("/#")) {
                throw new NetworkException(String.format("Topic中'#'使用不正确 ，topic = %s", topic));
            }
        }
        if (topic.contains("+")) {
            // '+'不能出现在层级以外的地方（比如 a+b/c），而且必须单独占一个层级
            String[] levels = topic.split("/");
            for (String level : levels) {
                if (level.contains("+") && !level.equals("+")) {
                    throw new NetworkException(String.format("Topic中'+'使用不正确 ，topic = %s", topic));
                }
            }
        }
    }

}
